package xiongguanweb.http

import com.alibaba.fastjson.JSON
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import xiongguanweb.AppConfig
import xiongguanweb.util.AhttpUtil
import xiongguanweb.util.PropKit

import javax.servlet.http.HttpSession
import java.util.concurrent.TimeUnit
import com.ijiami.JMEncryptBox

//调用示例
//
//【1】接口回调方式调用：
//        HttpClient.me().post("/v1/auth/token", params, null, new HttpClient.ResponseListener() {
//
//            @Override
//            void onSuccess(int code, JSONObject data) {
//                session.setAttribute("appToken", data.toJavaObject(AppToken.class))
//                render data as JSON
//            }
//
//            @Override
//            void onFailure(int code, String errorMsg) {
//
//            }
//
//            @Override
//            void onTokenExpired() {
//
//            }
//        })
//
//
//
//【2】闭包回调方式
//        HttpClient.me().post("/v1/auth/token", params, null) { result, data ->
//            switch (result) {
//                case Result.SUCCESS:
//                    render data as JSON
//                    break
//                case Result.FAILURE:
//
//                    break
//                case Result.TOKEN_EXPIRED:
//
//                    break
//            }
//        }
class HttpClient {
    private static Logger logger = LoggerFactory.getLogger(HttpClient.class);

    String BASE_URL
    {
        BASE_URL = PropKit.use("config.properties").getProperty("BASE_URL")
        logger.info("基础路径BASE_URL=" + BASE_URL);
    }

    private OkHttpClient okHttpClient;

    private static HttpClient instance;

    private HttpClient() {
        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .connectionPool(new ConnectionPool())
                .addNetworkInterceptor(httpLoggingInterceptor)
                .build();
    }

    static HttpClient me() {
        if (instance == null) {
            synchronized (HttpClient.class) {
                if (instance == null) {
                    instance = new HttpClient();
                }
            }
        }
        return instance;
    }

    //日志拦截器
    public HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
        @Override
        public void log(String message) {
            logger.info("http：" + message);
        }
    }).setLevel(HttpLoggingInterceptor.Level.BODY);

    /**
     * <p>
     * 默认http 请求方法
     *
     * @param url 接口地址
     * @param params RequestParams
     * @param onResponseListener OnResponseListener
     * @return Call
     */
    Call post(HttpSession session, RequestParams params, final OnResponseListener onResponseListener) {
        Request request = new Request.Builder()
                .post(setRequestBody(params))
                .headers(setRequestHeader(params))
                .url(BASE_URL)
                .build();
        Call calls = okHttpClient.newCall(request);
        Response response = calls.execute();

        if (response.isSuccessful()) {
            logger.info("请求数据==" + params.body.toString())
            String responseStr = response.body().string()

            xiongguanweb.http.response.Response responseData = null;
            try {
                if (AppConfig.dev) {
                    responseData = JSON.parseObject(responseStr, xiongguanweb.http.response.Response.class)
                    logger.info("接收报文(未加密)----->responseStr=" + responseStr);
                } else {
                    //解密数据
                    String decryptData = JMEncryptBox.decryptFromBase64(responseStr);

                    logger.info("接收报文(解密后)----->responseStr=" + decryptData);
                    //json解析报文
                    responseData = JSON.parseObject(decryptData, xiongguanweb.http.response.Response.class)
                }

                if (responseData == null) {
                    throw new Exception("返回报文为空");
                }
            } catch (Exception e) {
                onResponseListener.onFailure(-1, "解析数据异常[数据为空或json解析失败]，" + e.getMessage());
            }

            String jwt = response.header("Jwt")
            if (jwt != null && jwt.length() > 0) {
                session.setAttribute(AppConfig.TOKEN, jwt)
            }
            if ("10000002".equals(responseData.getHeader().getErrorcode())) { //10000002 --用户未登录
                onResponseListener.onTokenExpired(401, session);

            } else if (!"00000000".equals(responseData.getHeader().getErrorcode())) {//00000000 --成功

                onResponseListener.onFailure(Integer.parseInt(responseData.getHeader().getErrorcode()),
                        responseData.getHeader().getErrormsg());
            } else {
                onResponseListener.onSuccess(Integer.parseInt(responseData.getHeader().getErrorcode()),
                        responseData.getHeader().getErrormsg(), responseData.getData());
            }
        } else {
            onResponseListener.onFailure(-1, "服务器打了个瞌睡,code=" + response.code());
        }

        return calls;

    }

    /**
     * <p>
     * 默认http 请求方法
     *
     * @param url 接口地址
     * @param params RequestParams
     * @param onResponseListener OnResponseListener
     * @return Call
     */
    Call post(String url, HttpSession session, RequestParams params, final OnResponseListener onResponseListener) {
        Request request = new Request.Builder()
                .post(setRequestBody(params))
                .headers(setRequestHeader(params))
                .url(BASE_URL + url)
                .build();
        Call calls = okHttpClient.newCall(request);
        Response response = calls.execute();

        if (response.isSuccessful()) {
            String responseStr = response.body().string()

            xiongguanweb.http.response.Response responseData = null;
            try {
                if (AppConfig.dev) {
                    responseData = JSON.parseObject(responseStr, xiongguanweb.http.response.Response.class)
                    logger.info("接收报文(未加密)----->responseStr=" + responseStr);
                } else {
                    //解密数据
                    String decryptData = JMEncryptBox.decryptFromBase64(responseStr);

                    logger.info("接收报文(解密后)----->responseStr=" + decryptData);
                    //json解析报文
                    responseData = JSON.parseObject(decryptData, xiongguanweb.http.response.Response.class)
                }

                if (responseData == null) {
                    throw new Exception("返回报文为空");
                }
            } catch (Exception e) {
                onResponseListener.onFailure(-1, "解析数据异常[数据为空或json解析失败]，" + e.getMessage());
            }
            String jwt = response.header("Jwt")
            if (jwt != null && jwt.length() > 0) {
                session.setAttribute(AppConfig.TOKEN, jwt)
            }
            if ("10000002".equals(responseData.getHeader().getErrorcode())) { //10000002 --用户未登录
                onResponseListener.onTokenExpired(401, session);

            } else if (!"00000000".equals(responseData.getHeader().getErrorcode())) {//00000000 --成功

                onResponseListener.onFailure(Integer.parseInt(responseData.getHeader().getErrorcode()),
                        responseData.getHeader().getErrormsg());
            } else {

                onResponseListener.onSuccess(Integer.parseInt(responseData.getHeader().getErrorcode()),
                        responseData.getHeader().getErrormsg(), responseData.getData());
            }
        } else {
            onResponseListener.onFailure(-1, "服务器打了个瞌睡,code=" + response.code());
        }

        return calls;
    }

    //带参数上传文件
    public Call uploadFileWithParams(String url, RequestParams params, String fileKey, File file, final OnResponseListener onResponseListener) {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        builder.addFormDataPart(fileKey, file.getName(), RequestBody.create(MediaType.parse("image/png"), file));

        Request request = new Request.Builder()
                .headers(setRequestHeader(params))
                .tag("http_upload")
                .url(url)
                .post(setRequestMultipartBody(params, builder))
                .build();

        logger.info("请求数据==" + params.body.toString())
        Call calls = okHttpClient.newCall(request);
        calls.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if (e.getMessage().contains("Failed to connect to")) {
                    onResponseListener.onFailure("-1", "网络异常，[" + "连不上网络啦" + "]");
                } else {
                    onResponseListener.onFailure("-1", "网络异常，[" + e.getMessage() + "]");
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.code() == 200) {
                    String responseMessage = response.body().string();
                    xiongguanweb.http.response.Response responseData = null;
                    try {
                        responseData = JSON.parseObject(responseMessage, xiongguanweb.http.response.Response.class);
//                        if (AppConfig.dev) {
//                            responseData = JSON.parseObject(responseMessage, com.citycloud.xiongguan.app.core.http.response.Response.class);
//                            Log.i("TAG_DEBUG", "onResponse(AHttp.java) 接收报文debug----->responseMessage=" + responseMessage);
//                        } else {
//                            //解密数据
//                            String decryptData = JMEncryptBox.decryptFromBase64(responseMessage);
//                            Log.i("TAG", "onResponse(AHttp.java) 接收报文(解密后)----->responseMessage=" + decryptData);
//                            //解析报文
//                            responseData = JSON.parseObject(decryptData, com.citycloud.xiongguan.app.core.http.response.Response.class);
//                        }

                        if (responseData == null) {
                            throw new Exception("返回报文为空");
                        }
                    } catch (Exception e) {
                        onResponseListener.onFailure(-1, "解析数据异常，" + e.getMessage());
                    }

                    if ("10000002".equals(responseData.getHeader().getErrorcode())) { //10000002 --用户未登录
                        onResponseListener.onTokenExpired(401, session);
                    } else if (!"00000000".equals(responseData.getHeader().getErrorcode())) {//00000000 --成功
                        onResponseListener.onFailure(Integer.parseInt(responseData.getHeader().getErrorcode()), responseData.getHeader().getErrormsg());
                    } else {
                        onResponseListener.onSuccess(Integer.parseInt(responseData.getHeader().getErrorcode()), responseData.getHeader().getErrormsg(), responseData.getData());
                    }
                } else {
                    onResponseListener.onFailure(-1, "服务器打了个瞌睡,code=" + response.code());
                }
            }
        });
        return calls;
    }

    /**
     * <p>
     * 默认http 请求方法
     *
     * @param url 接口地址
     * @param params RequestParams
     * @param onResponseListener OnResponseListener
     * @return Call
     */
    String gethtml(String url) {
        Request request = new Request.Builder()
                .url(url)
                .build()
        Call calls = okHttpClient.newCall(request)
        Response response = calls.execute()
        String responseStr = response.body().string()

        return responseStr
    }

/**
 * @param params
 * @return
 */
    private RequestBody setRequestMultipartBody(RequestParams params, MultipartBody.Builder builder) {
        //创建RequestBody
        if (params != null) {
            try {
                String requestMessage;
                requestMessage = AhttpUtil.getRequestJson(params);
//                if (AppConfig.dev) {
//                    Log.i("TAG_DEBUG", "setRequestBody(AHttp.java)请求报文debug----->requestMessage=" + requestMessage);
//                } else {
//                    requestMessage = JMEncryptBox.encryptToBase64(AhttpUtil.getRequestJson(params));
//                    Log.i("TAG", "setRequestBody(AHttp.java)请求报文加密----->requestMessage=" + requestMessage);
//                }
                builder.addFormDataPart("content", requestMessage);
            } catch (Exception e) {
//                Log.e("TAG", "setRequestBody(AHttp.java)" + e.getStackTrace());
            }
        }
        return builder.build();
    }

/**
 * HTTP 请求体数据设置
 *
 * @param params
 * @return
 */
    private RequestBody setRequestBody(RequestParams params) {
        RequestBody body = null;
        FormBody.Builder formEncodingBuilder = new okhttp3.FormBody.Builder();
        if (params != null) {
            try {
                String requestMessage;
                if (AppConfig.dev) {
                    requestMessage = AhttpUtil.getRequestJson(params);
//                    Log.i("TAG_DEBUG", "setRequestBody(AHttp.java)请求报文debug----->requestMessage=" + requestMessage);
                } else {
                    requestMessage = JMEncryptBox.encryptToBase64(AhttpUtil.getRequestJson(params));
//                    Log.i("TAG", "setRequestBody(AHttp.java)请求报文加密----->requestMessage=" + requestMessage);
                }

                formEncodingBuilder.add("content", requestMessage);
            } catch (Exception e) {

//                Log.e("TAG", "setRequestBody(AHttp.java)" + e.getStackTrace());
            }
        }
        body = formEncodingBuilder.build();
        return body;
    }

/**
 * HTTP 请求头数据设置
 *
 * @param params
 * @return
 */
    private Headers setRequestHeader(RequestParams params) {
        Headers headers = null;
        Map<String, String> headersParams = params.getHeads();
        Headers.Builder headersbuilder = new Headers.Builder();
        //设置头参数
        if (headersParams != null) {
            Iterator<String> iterator = headersParams.keySet().iterator();
            String key = "";
            while (iterator.hasNext()) {
                key = iterator.next().toString();
                headersbuilder.add(key, headersParams.get(key));
            }
        }
        headers = headersbuilder.build();
        return headers;
    }

}
